package edu.hawaii.duedates.configuration;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.File;

import org.junit.Before;
import org.junit.Test;

import edu.hawaii.duedates.datastore.DueDatesConfig;

/**
 * A unit test for the ConfigurationManager that assures the xml file is being parsed correctly.  
 * The user's password does not have a setter or getter, testing for assurance is possible through 
 * boolean only.
 * 
 * @author Daniel Arakaki, Jeho Jung, Arthur Shum, Daniel Tian
 * @version 1.0, November 26, 2008
 */
public class TestConfigurationManager {
  
  /**A variable for the DueDatesConfig. */
  private DueDatesConfig dueDates;
  
  /**The root directory for the xml files. */
  private static final String USER_DIR = "user.dir";
  
  private static final String XSDFILE = "/xml/duedates.definition.xsd";
  
  /**
   * Instantiate objects to set up the test.
   */
  @Before
  public void setUp() {
    File dueDatesExample = new File(System.getProperty(USER_DIR) + "/xml/duedates.example.xml");
    File dueDatesXsd = new File(System.getProperty(USER_DIR) + XSDFILE);
    ConfigurationManager manager = new ConfigurationManager(dueDatesExample, dueDatesXsd);
    this.dueDates = manager.getDueDatesConfig();
  }
  
  /**
   * Test that ConfigurationManager throws an exception if it can't find the XML file.
   * 
   * @throws Exception If it can't find the XML file.
   */
  @Test(expected = Exception.class)
  public void testMissingFile() throws Exception {
    File xmlfile = new File(System.getProperty(USER_DIR) + "/xml/missingfile.xml");
    File xsdfile = new File(System.getProperty(USER_DIR) + XSDFILE);
    ConfigurationManager manager = new ConfigurationManager(xmlfile, xsdfile);
    this.dueDates = manager.getDueDatesConfig();
    fail("Should not get here.");
  }
  
  /**
   * Test that ConfigurationManager throws an exception if the XML file is invalid.
   * 
   * @throws Exception If the XML file is invalid.
   */
  @Test(expected = Exception.class)
  public void testInvalidFile() throws Exception {
    File xmlfile = new File(System.getProperty(USER_DIR) + "/xml/duedates.test0.xml");
    File xsdfile = new File(System.getProperty(USER_DIR) + XSDFILE);
    ConfigurationManager manager = new ConfigurationManager(xmlfile, xsdfile);
    this.dueDates = manager.getDueDatesConfig();
    fail("Should not get here.");
  }

  /**
   * Test that ConfigurationManager throws an exception if the user specifies an unknown library.
   * 
   * @throws Exception If the user specifies an unknown library.
   */
  @Test(expected = Exception.class)
  public void testUnknownLibrary1() throws Exception {
    File xmlfile = new File(System.getProperty(USER_DIR) + "/xml/duedates.test1.xml");
    File xsdfile = new File(System.getProperty(USER_DIR) + XSDFILE);
    ConfigurationManager cm = new ConfigurationManager(xmlfile, xsdfile);
    cm.getDueDatesConfig();
    fail("Should not reach here.");
  }
  
  /**
   * Test that ConfigurationManager throws an exception if the user specifies an unknown library.
   * 
   * @throws Exception If the user specifies an unknown library.
   */  
  @Test(expected = Exception.class)
  public void testUnknownLibrary2() throws Exception {
    File xmlfile = new File(System.getProperty(USER_DIR) + "/xml/duedates.test2.xml");
    File xsdfile = new File(System.getProperty(USER_DIR) + XSDFILE);
    ConfigurationManager cm = new ConfigurationManager(xmlfile, xsdfile);
    cm.getDueDatesConfig();
    fail("Should not reach here.");
  }
  
  /**
   * Test that ConfigurationManager throws an exception if the class that it is trying to load is
   * missing.
   * 
   * @throws Exception If the class that it is trying to load is missing.
   */  
  @Test(expected = Exception.class)
  public void testMissingClass() throws Exception {
    File xmlfile = new File(System.getProperty(USER_DIR) + "/xml/duedates.test3.xml");
    File xsdfile = new File(System.getProperty(USER_DIR) + XSDFILE);
    ConfigurationManager cm = new ConfigurationManager(xmlfile, xsdfile);
    cm.getDueDatesConfig();
    fail("Shouldn't get here.");
  }
  
  /**
   * Test that ConfigurationManager can successfully instantiate a class using reflection.
   * 
   * @throws Exception If something goes wrong during the test.
   */  
  @Test
  public void testMakeObject() throws Exception {
    File xmlfile = new File(System.getProperty(USER_DIR) + "/xml/duedates.test4.xml");
    File xsdfile = new File(System.getProperty(USER_DIR) + XSDFILE);
    ConfigurationManager cm = new ConfigurationManager(xmlfile, xsdfile);
    DueDatesConfig config = cm.getDueDatesConfig();
    assertFalse("The config object should contain data", config.getUsers().isEmpty());
  }
  
  ////////////////////////////
  
  /**
   * Test for the smtp server.
   */
  @Test
  public void testGetSmtpServer() {
    assertEquals("Testing for the smtp server.", "mail.hawaii.edu", this.dueDates.getSmtpServer());
  }
  
  /**
   * Test for the user's name.
   */
  @Test
  public void testGetUserName() {
    assertEquals("Testing for the user's name.", "Philip Johnson", 
        this.dueDates.getUsers().get(0).getName());
    assertEquals("Testing for the user's name.", "Shaoxuan Zhang", 
        this.dueDates.getUsers().get(1).getName());
  }
  
  /**
   * Test for the user's email address.
   */
  @Test
  public void testGetEmailAddress() {
    assertEquals("Testing for the user's email address.", "johnson@hawaii.edu",
        this.dueDates.getUsers().get(0).getEmail());
    assertEquals("Testing for the user's email address.", "sz@hawaii.edu",
        this.dueDates.getUsers().get(1).getEmail());
  }
  
  /**
   * Test for the user's login password.
   */
  @Test
  public void testPassword() {
    assertTrue("Testing for the user's password.", 
        this.dueDates.getUsers().get(0).isValidUser("johnson@hawaii.edu", "password"));
  }
  
  /**
   * Test for missing values.
   */
  @Test
  public void testNullValue() {
    assertFalse("Testing for invalid password.",
        this.dueDates.getUsers().get(1).isValidUser("sz@hawaii.edu", null));
    assertFalse("Testing for invalid password.",
        this.dueDates.getUsers().get(1).isValidUser(null, "password"));
  }
  
  /**
   * Test for the library's name.
   */
  @Test
  public void testGetLibrary() {
    assertEquals("Testing for the library's name", "University of Hawaii", 
        this.dueDates.getUsers().get(0).getLibraryList().get(0).getName());
    assertEquals("Testing for the library's name", "Hawaii State Library",
        this.dueDates.getUsers().get(0).getLibraryList().get(1).getName());
  }

}
